import pygame
import os,random

#设置常量
W,H = (288,512)
FPS = 30
IMAGES = {}
PIPE_GAP = 300
PIPE_GAP_UPDOWN = 100
PIPE_COUNT = 3


#设置初始化设置
pygame.init()
SCREEN = pygame.display.set_mode((W,H))
pygame.display.set_caption("快乐的小鸟")

icon = pygame.image.load("./assets/sprites/red-mid.png")
pygame.display.set_icon(icon)

CLOCK = pygame.time.Clock()
score = 0

#载入素材
for image in os.listdir('./assets/sprites'):
    name,extension = os.path.splitext(image)
    path = './assets/sprites/' + image
    IMAGES[name] = pygame.image.load(path)

die_sound = pygame.mixer.Sound("./assets/audio/die.wav")
flap_sound = pygame.mixer.Sound("./assets/audio/flap.wav")
hit_sound = pygame.mixer.Sound("./assets/audio/hit.wav")
score_sound = pygame.mixer.Sound("./assets/audio/score.wav")
start_sound = pygame.mixer.Sound("./assets/audio/start.wav")
back_music = pygame.mixer.Sound("./assets/audio/back_music.mp3")
start_button_music =   pygame.mixer.Sound("./assets/audio/start_button.mp3")

FLOOR_H = IMAGES["day"].get_height() - IMAGES["floor"].get_height()

#全局变量小鸟
bird = 0

def main():
    global bird,score
    flap_sound.play()
    while True:
        color = random.choice(['red', 'yellow', 'blue'])
        IMAGES["bird"] = [IMAGES[color + "-down"], IMAGES[color + "-mid"], IMAGES[color + "-up"]]
        IMAGES['bpic'] = IMAGES[random.choice(['day', 'night'])]

        color = random.choice(["green", "red"])
        IMAGES["pipes"] = [IMAGES[color + "-pipe"], pygame.transform.flip(IMAGES[color + "-pipe"], False, True)]
        bird = Bird(50, 230)

        start_sound.play()
        score = 0
        back_music.play(-1)

        menu_window()
        pipe_group = game_window()

        back_music.stop()
        end_window({"pipe_group":pipe_group})

def menu_window():
    global  bird
    floor_gap = IMAGES["floor"].get_width()  - IMAGES["bpic"].get_width()
    floor_x = 0

    bird_y = 230
    bird_y_change = 1
    bird_y_range = (bird_y-10,bird_y+10)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                start_button_music.play()
                return

        floor_x -= 4
        if floor_x <= -floor_gap:
            floor_x = 0

        bird.rect.y += bird_y_change
        if bird.rect.y < bird_y_range[0] or bird.rect.y > bird_y_range[1]:
            bird_y_change = -bird_y_change

        bird.update_fly()

        SCREEN.blit(IMAGES['bpic'],(0,0))
        SCREEN.blit(IMAGES['guide'],((W-IMAGES['guide'].get_width())/2,(FLOOR_H - IMAGES['guide'].get_height())/2))
        SCREEN.blit(IMAGES['floor'], (floor_x, H - IMAGES['floor'].get_height()))
        SCREEN.blit(bird.image,bird.rect)
        pygame.display.update()
        CLOCK.tick(FPS)

def game_window():
    global  bird,score
    floor_gap = IMAGES["floor"].get_width()  - IMAGES["bpic"].get_width()
    floor_x = 0

    pipe_group = pygame.sprite.Group()
    for i in range(PIPE_COUNT):
        x = W + i * PIPE_GAP
        y =  random.randint(FLOOR_H-(H - 200),FLOOR_H - 20)
        pipe_group.add(Pipe(x,y,False))
        pipe_group.add(Pipe(x,y-PIPE_GAP_UPDOWN,True))

    while True:
        flap = False
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                flap = True
                flap_sound.play()

        up = pipe_group.sprites()[0]
        down = pipe_group.sprites()[1]
        if up.rect.x < -IMAGES["pipes"][0].get_width():
            score += 1
            score_sound.play()
            new_x = pipe_group.sprites()[-1].rect.x + PIPE_GAP
            new_y = random.randint(FLOOR_H-(H - 200),FLOOR_H - 20)

            up.kill()
            down.kill()

            pipe_group.add(Pipe(new_x,new_y,False))
            pipe_group.add(Pipe(new_x, new_y - PIPE_GAP_UPDOWN, True))

        floor_x -= 4
        if floor_x <= -floor_gap:
            floor_x = 0

        #游戏结束判断
        if bird.rect.y > FLOOR_H or bird.rect.y < 0 or pygame.sprite.spritecollide(bird,pipe_group,False):
            hit_sound.play()
            die_sound.play()
            return pipe_group



        bird.update(flap)

        pipe_group.update()

        SCREEN.blit(IMAGES['bpic'],(0,0))
        pipe_group.draw(SCREEN)
        SCREEN.blit(IMAGES['floor'], (floor_x, H - IMAGES['floor'].get_height()))
        SCREEN.blit(bird.image,bird.rect)
        pygame.display.update()
        CLOCK.tick(FPS)

def end_window(results):
    global bird
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                quit()
            elif event.type == pygame.KEYDOWN and event.key == pygame.K_SPACE:
                return

        #播放死亡动画
        bird.dieAmation()

        SCREEN.blit(IMAGES['bpic'],(0,0))
        results["pipe_group"].draw(SCREEN)
        SCREEN.blit(IMAGES['floor'], (0, H - IMAGES['floor'].get_height()))
        SCREEN.blit(IMAGES["gameover"], ((W - IMAGES["gameover"].get_width())/2, (H-IMAGES["gameover"].get_height())/2))
        SCREEN.blit(IMAGES[str(score//100)],((W-IMAGES["1"].get_width())/2-IMAGES["1"].get_width()-10,20))
        SCREEN.blit(IMAGES[str(score // 10 %10)],((W - IMAGES["1"].get_width()) / 2, 20))
        SCREEN.blit(IMAGES[str(score% 10)],((W - IMAGES["1"].get_width()) / 2+IMAGES["1"].get_width()+10, 20))
        SCREEN.blit(bird.image,bird.rect)
        pygame.display.update()
        CLOCK.tick(FPS)

class Pipe(pygame.sprite.Sprite):
    def __init__(self,x,y,uptodown = False):
        super().__init__()
        if uptodown:
            self.image = IMAGES['pipes'][1]
            self.rect = self.image.get_rect()
            self.rect.x = x
            self.rect.bottom = y
        else:
            self.image = IMAGES['pipes'][0]
            self.rect = self.image.get_rect()
            self.rect.x = x
            self.rect.y = y
        self.x_vel = -4

    def update(self):
        self.rect.x += self.x_vel

class Bird:
    def __init__(self,x,y):
        self.frames = [0,0,0,0,0,1,1,1,1,1,2,2,2,2,1,1,1,1,1,1,0,0,0,0,0]
        self.idx = 0
        self.image = IMAGES['bird'][self.frames[self.idx]]
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y


        self.y_vel = -10
        self.max_y_vel = 10
        self.gravity = 1

        self.rotate = 45
        self.max_rotate = -20
        self.rotate_vel = -3

        self.v_vel_after_flap = -10
        self.rotate_after_flap = 45

    def update_fly(self):
        self.idx += 1
        self.idx %= len(self.frames)
        self.image = IMAGES['bird'][self.frames[self.idx]]

    def update(self,flap = False):
        if flap:
            self.y_vel = self.v_vel_after_flap
            self.rotate = self.rotate_after_flap

        self.y_vel = min(self.y_vel + self.gravity,self.max_y_vel)
        self.rect.y += self.y_vel

        self.rotate = max(self.rotate_vel + self.rotate,self.max_rotate)


        self.update_fly()
        self.image = pygame.transform.rotate(self.image, self.rotate)

    def dieAmation(self):
        if self.rect.y < FLOOR_H:
            self.rotate = -90
            self.image = pygame.transform.rotate(self.image, self.rotate)
            self.rect.y += 10



if __name__ == '__main__':
    main()